﻿namespace ch07.binary.interpreter
{
    public static partial class Instr
    {
        private static InstrFn[] InstrTable;

        internal static InstrFn[] GetInstrFn()
        {
            if (InstrTable != null) return InstrTable;
            InstrTable = new InstrFn[256];
            Init();

            return InstrTable;
        }

        private static void Init()
        {
            InstrTable[OpCodes.BrIf] = brIf;
            
            InstrTable[OpCodes.Call] = Call; // hack!
            InstrTable[OpCodes.Drop] = Drop;
            InstrTable[OpCodes.Select] = Select;

            //func
            InstrTable[OpCodes.LocalGet] = localGet;
            InstrTable[OpCodes.LocalSet] = localSet;
            InstrTable[OpCodes.LocalTee] = localTee;
            InstrTable[OpCodes.GlobalGet] = globalGet;
            InstrTable[OpCodes.GlobalSet] = globalSet;

            //memory cmd
            InstrTable[OpCodes.I32Load] = I32Load;
            InstrTable[OpCodes.I64Load] = I64Load;
            InstrTable[OpCodes.F32Load] = F32Load;
            InstrTable[OpCodes.F64Load] = F64Load;
            InstrTable[OpCodes.I32Load8S] = I32Load8S;
            InstrTable[OpCodes.I32Load8U] = I32Load8U;
            InstrTable[OpCodes.I32Load16S] = I32Load16S;
            InstrTable[OpCodes.I32Load16U] = I32Load16U;
            InstrTable[OpCodes.I64Load8S] = I64Load8S;
            InstrTable[OpCodes.I64Load8U] = I64Load8U;
            InstrTable[OpCodes.I64Load16S] = I64Load16S;
            InstrTable[OpCodes.I64Load16U] = I64Load16U;
            InstrTable[OpCodes.I64Load32S] = I64Load32S;
            InstrTable[OpCodes.I64Load32U] = I64Load32U;
            InstrTable[OpCodes.I32Store] = I32Store;
            InstrTable[OpCodes.I64Store] = I64Store;
            InstrTable[OpCodes.F32Store] = F32Store;
            InstrTable[OpCodes.F64Store] = F64Store;
            InstrTable[OpCodes.I32Store8] = I32Store8;
            InstrTable[OpCodes.I32Store16] = I32Store16;
            InstrTable[OpCodes.I64Store8] = I64Store8;
            InstrTable[OpCodes.I64Store16] = I64Store16;
            InstrTable[OpCodes.I64Store32] = I64Store32;
            InstrTable[OpCodes.MemorySize] = MemorySize;
            InstrTable[OpCodes.MemoryGrow] = MemoryGrow;

            InstrTable[OpCodes.I32Const] = I32Const;
            InstrTable[OpCodes.I64Const] = I64Const;
            InstrTable[OpCodes.F32Const] = F32Const;
            InstrTable[OpCodes.F64Const] = F64Const;
            InstrTable[OpCodes.I32Eqz] = I32Eqz;
            InstrTable[OpCodes.I32Eq] = I32Eq;
            InstrTable[OpCodes.I32Ne] = I32Ne;
            InstrTable[OpCodes.I32LtS] = I32LtS;
            InstrTable[OpCodes.I32LtU] = I32LtU;
            InstrTable[OpCodes.I32GtS] = I32GtS;
            InstrTable[OpCodes.I32GtU] = I32GtU;
            InstrTable[OpCodes.I32LeS] = I32LeS;
            InstrTable[OpCodes.I32LeU] = I32LeU;
            InstrTable[OpCodes.I32GeS] = I32GeS;
            InstrTable[OpCodes.I32GeU] = I32GeU;
            InstrTable[OpCodes.I64Eqz] = I64Eqz;
            InstrTable[OpCodes.I64Eq] = I64Eq;
            InstrTable[OpCodes.I64Ne] = I64Ne;
            InstrTable[OpCodes.I64LtS] = I64LtS;
            InstrTable[OpCodes.I64LtU] = I64LtU;
            InstrTable[OpCodes.I64GtS] = I64GtS;
            InstrTable[OpCodes.I64GtU] = I64GtU;
            InstrTable[OpCodes.I64LeS] = I64LeS;
            InstrTable[OpCodes.I64LeU] = I64LeU;
            InstrTable[OpCodes.I64GeS] = I64GeS;
            InstrTable[OpCodes.I64GeU] = I64GeU;
            InstrTable[OpCodes.F32Eq] = F32Eq;
            InstrTable[OpCodes.F32Ne] = F32Ne;
            InstrTable[OpCodes.F32Lt] = F32Lt;
            InstrTable[OpCodes.F32Gt] = F32Gt;
            InstrTable[OpCodes.F32Le] = F32Le;
            InstrTable[OpCodes.F32Ge] = F32Ge;
            InstrTable[OpCodes.F64Eq] = F64Eq;
            InstrTable[OpCodes.F64Ne] = F64Ne;
            InstrTable[OpCodes.F64Lt] = F64Lt;
            InstrTable[OpCodes.F64Gt] = F64Gt;
            InstrTable[OpCodes.F64Le] = F64Le;
            InstrTable[OpCodes.F64Ge] = F64Ge;
            InstrTable[OpCodes.I32Clz] = I32Clz;
            InstrTable[OpCodes.I32Ctz] = I32Ctz;
            InstrTable[OpCodes.I32PopCnt] = I32PopCnt;
            InstrTable[OpCodes.I32Add] = I32Add;
            InstrTable[OpCodes.I32Sub] = I32Sub;
            InstrTable[OpCodes.I32Mul] = I32Mul;
            InstrTable[OpCodes.I32DivS] = I32DivS;
            InstrTable[OpCodes.I32DivU] = I32DivU;
            InstrTable[OpCodes.I32RemS] = I32RemS;
            InstrTable[OpCodes.I32RemU] = I32RemU;
            InstrTable[OpCodes.I32And] = I32And;
            InstrTable[OpCodes.I32Or] = I32Or;
            InstrTable[OpCodes.I32Xor] = I32Xor;
            InstrTable[OpCodes.I32Shl] = I32Shl;
            InstrTable[OpCodes.I32ShrS] = I32ShrS;
            InstrTable[OpCodes.I32ShrU] = I32ShrU;
            InstrTable[OpCodes.I32Rotl] = I32Rotl;
            InstrTable[OpCodes.I32Rotr] = I32Rotr;
            InstrTable[OpCodes.I64Clz] = I64Clz;
            InstrTable[OpCodes.I64Ctz] = I64Ctz;
            InstrTable[OpCodes.I64PopCnt] = I64PopCnt;
            InstrTable[OpCodes.I64Add] = I64Add;
            InstrTable[OpCodes.I64Sub] = I64Sub;
            InstrTable[OpCodes.I64Mul] = I64Mul;
            InstrTable[OpCodes.I64DivS] = I64DivS;
            InstrTable[OpCodes.I64DivU] = I64DivU;
            InstrTable[OpCodes.I64RemS] = I64RemS;
            InstrTable[OpCodes.I64RemU] = I64RemU;
            InstrTable[OpCodes.I64And] = I64And;
            InstrTable[OpCodes.I64Or] = I64Or;
            InstrTable[OpCodes.I64Xor] = I64Xor;
            InstrTable[OpCodes.I64Shl] = I64Shl;
            InstrTable[OpCodes.I64ShrS] = I64ShrS;
            InstrTable[OpCodes.I64ShrU] = I64ShrU;
            InstrTable[OpCodes.I64Rotl] = I64Rotl;
            InstrTable[OpCodes.I64Rotr] = I64Rotr;
            InstrTable[OpCodes.F32Abs] = F32Abs;
            InstrTable[OpCodes.F32Neg] = F32Neg;
            InstrTable[OpCodes.F32Ceil] = F32Ceil;
            InstrTable[OpCodes.F32Floor] = F32Floor;
            InstrTable[OpCodes.F32Trunc] = F32Trunc;
            InstrTable[OpCodes.F32Nearest] = F32Nearest;
            InstrTable[OpCodes.F32Sqrt] = F32Sqrt;
            InstrTable[OpCodes.F32Add] = F32Add;
            InstrTable[OpCodes.F32Sub] = F32Sub;
            InstrTable[OpCodes.F32Mul] = F32Mul;
            InstrTable[OpCodes.F32Div] = F32Div;
            InstrTable[OpCodes.F32Min] = F32Min;
            InstrTable[OpCodes.F32Max] = F32Max;
            InstrTable[OpCodes.F32CopySign] = F32CopySign;
            InstrTable[OpCodes.F64Abs] = F64Abs;
            InstrTable[OpCodes.F64Neg] = F64Neg;
            InstrTable[OpCodes.F64Ceil] = F64Ceil;
            InstrTable[OpCodes.F64Floor] = F64Floor;
            InstrTable[OpCodes.F64Trunc] = F64Trunc;
            InstrTable[OpCodes.F64Nearest] = F64Nearest;
            InstrTable[OpCodes.F64Sqrt] = F64Sqrt;
            InstrTable[OpCodes.F64Add] = F64Add;
            InstrTable[OpCodes.F64Sub] = F64Sub;
            InstrTable[OpCodes.F64Mul] = F64Mul;
            InstrTable[OpCodes.F64Div] = F64Div;
            InstrTable[OpCodes.F64Min] = F64Min;
            InstrTable[OpCodes.F64Max] = F64Max;
            InstrTable[OpCodes.F64CopySign] = F64CopySign;
            InstrTable[OpCodes.I32WrapI64] = I32WrapI64;
            InstrTable[OpCodes.I32TruncF32S] = I32TruncF32S;
            InstrTable[OpCodes.I32TruncF32U] = I32TruncF32U;
            InstrTable[OpCodes.I32TruncF64S] = I32TruncF64S;
            InstrTable[OpCodes.I32TruncF64U] = I32TruncF64U;
            InstrTable[OpCodes.I64ExtendI32S] = I64ExtendI32S;
            InstrTable[OpCodes.I64ExtendI32U] = I64ExtendI32U;
            InstrTable[OpCodes.I64TruncF32S] = I64TruncF32S;
            InstrTable[OpCodes.I64TruncF32U] = I64TruncF32U;
            InstrTable[OpCodes.I64TruncF64S] = I64TruncF64S;
            InstrTable[OpCodes.I64TruncF64U] = I64TruncF64U;
            InstrTable[OpCodes.F32ConvertI32S] = F32ConvertI32S;
            InstrTable[OpCodes.F32ConvertI32U] = F32ConvertI32U;
            InstrTable[OpCodes.F32ConvertI64S] = F32ConvertI64S;
            InstrTable[OpCodes.F32ConvertI64U] = F32ConvertI64U;
            InstrTable[OpCodes.F32DemoteF64] = F32DemoteF64;
            InstrTable[OpCodes.F64ConvertI32S] = F64ConvertI32S;
            InstrTable[OpCodes.F64ConvertI32U] = F64ConvertI32U;
            InstrTable[OpCodes.F64ConvertI64S] = F64ConvertI64S;
            InstrTable[OpCodes.F64ConvertI64U] = F64ConvertI64U;
            InstrTable[OpCodes.F64PromoteF32] = F64PromoteF32;
            InstrTable[OpCodes.I32ReinterpretF32] = I32ReinterpretF32;
            InstrTable[OpCodes.I64ReinterpretF64] = I64ReinterpretF64;
            InstrTable[OpCodes.F32ReinterpretI32] = F32ReinterpretI32;
            InstrTable[OpCodes.F64ReinterpretI64] = F64ReinterpretI64;
            InstrTable[OpCodes.I32Extend8S] = I32Extend8S;
            InstrTable[OpCodes.I32Extend16S] = I32Extend16S;
            InstrTable[OpCodes.I64Extend8S] = I64Extend8S;
            InstrTable[OpCodes.I64Extend16S] = I64Extend16S;
            InstrTable[OpCodes.I64Extend32S] = I64Extend32S;
            InstrTable[OpCodes.TruncSat] = TruncSat;
        }
    }
}